package com.thyme.content.service.content;

import com.thyme.content.dao.content.ShareMapper;
import com.thyme.content.dao.messaging.RocketmqTransactionLogMapper;
import com.thyme.content.domain.dto.content.ShareAuditDTO;
import com.thyme.content.domain.dto.content.ShareDTO;
import com.thyme.content.domain.dto.messaging.UserAddBonusMsgDTO;
import com.thyme.content.domain.dto.user.UserDTO;
import com.thyme.content.domain.entity.content.Share;
import com.thyme.content.domain.entity.messaging.RocketmqTransactionLog;
import com.thyme.content.domain.enums.AuditStatusEnum;
import com.thyme.content.feignclient.CenterUserFeignClient;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.apache.rocketmq.spring.support.RocketMQHeaders;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import java.util.List;
import java.util.Objects;
import java.util.UUID;

/**
 * @author thyme
 * @ClassName ShareService
 * @Description TODO
 * @Date 2019/10/31 9:54
 */
@Slf4j
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class ShareService {

    private final ShareMapper shareMapper;

    private final RestTemplate restTemplate;

    private final DiscoveryClient discoveryClient;

    private final CenterUserFeignClient centerUserFeignClient;

    private final RocketMQTemplate rocketMQTemplate;

    private final RocketmqTransactionLogMapper rocketmqTransactionLogMapper;


    public ShareDTO findById(Integer id) {
        //获取分享详情
        Share share = this.shareMapper.selectByPrimaryKey(id);
        //发布人id
        Integer userId = share.getUserId();
        // 怎么调用微服务获取
        // 第一种利用
        //用户中心所有实例的信息
//        List<ServiceInstance> instances = discoveryClient.getInstances("center-user");
//        String targetURL = instances.stream().map(instance -> instance.getUri().toString() + "/users/{id}")
//                .findFirst()
//                .orElseThrow(() -> new IllegalArgumentException("当前没有实例"));
//        // 怎么调用微服务获取
//        // 第一种利用
//        //UserDTO userDTO = restTemplate.getForObject("http://localhost:8080/users/{id}", UserDTO.class, userId);
//
//        //第二种利用discoveryClient 获取实例
//        log.info("请求的目标地址：{}",targetURL);

        // 第三种 使用ribbon
        //       UserDTO userDTO = restTemplate.getForObject("http://center-user/users/{userId}", UserDTO.class, userId);
        // 第四种 使用feign实现远程HTTP 调用
        UserDTO userDTO = centerUserFeignClient.findById(userId);
        //消息装配
        ShareDTO shareDTO = new ShareDTO();
        BeanUtils.copyProperties(share, shareDTO);
        shareDTO.setWxNickname(userDTO.getWxNickname());
        return shareDTO;
    }

    public Share auditById(Integer id, ShareAuditDTO auditDTO) {
        //1. 查询share是否存在，不存在或者当前的audit_status != NOT_YET,那么抛异常
        Share share = this.shareMapper.selectByPrimaryKey(id);
        if (share == null) {
            throw new IllegalArgumentException("参数非法！该分享不存在");
        }
        if (!Objects.equals("NOT_YET", share.getAuditStatus())) {
            throw new IllegalArgumentException("参数非法！该分享已经审核通过或者不通过");
        }

        //3. 如果是PASS，那么发送信息给rocketmq,让用户中心去消费并为为发布人添加积分
        if(AuditStatusEnum.PASS.equals(auditDTO.getAuditStatusEnum())) {
            //发送半消息
            String transactionId = UUID.randomUUID().toString();
            this.rocketMQTemplate.sendMessageInTransaction(
                    "tx-add-bonus-group",
                    "add-bonus",
                    MessageBuilder
                    .withPayload(UserAddBonusMsgDTO.builder()
                            .userId(share.getUserId())
                            .bonus(50)
                            .build())
                            //header有妙用
                            .setHeader(RocketMQHeaders.TRANSACTION_ID,transactionId)
                            .setHeader("share_id",id)
                    .build(),
                    // arg有大用处
                    auditDTO
            );
        } else {
            this.auditById(id,auditDTO);
        }
        //异步执行
        return share;
    }

    @Transactional(rollbackFor = Exception.class)
    public void auditByIdInDB(Integer id,ShareAuditDTO auditDTO) {
        //2. 审核资源，将状态设为PASS/REJECT
        Share share = Share.builder()
                .id(id)
                .auditStatus(auditDTO.getAuditStatusEnum().toString())
                .reason(auditDTO.getReason())
                .build();
        this.shareMapper.updateByPrimaryKeySelective(share);
    }

    @Transactional(rollbackFor = Exception.class)
    public void auditByIdWithRocketMqLog(Integer id,ShareAuditDTO auditDTO,String transactionId) {
        this.auditByIdInDB(id,auditDTO);
        this.rocketmqTransactionLogMapper.insertSelective(
                RocketmqTransactionLog.builder()
                .transactionId(transactionId)
                .log("审核分享...")
                .build()
        );

    }
}
